/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2022-2022. All rights reserved.
 * Description: 性能评估器相关源文件
 * Author: qingjicheng
 * Create: 2022-8-1
 */

#include "topo_split.h"
#include "evaluator_log_def.h"

namespace HcclEvaluator {
TopoSplit::TopoSplit()
{
}

TopoSplit::~TopoSplit()
{
}

HcclResult TopoSplit::Split(HcclTopology* topo, std::vector<AdjacencyMatrix<>> &matrixes)
{
    // 目前只支持单层拓扑
    AdjacencyMatrix<> matrix;
    std::vector<u32> nodeList;
    GetNodeList(topo, nodeList);
    EVALUATOR_CHK_RET(CheckNodeList(nodeList));

    TimePoint start = TimeNow();
    EVALUATOR_INFO("GetNodeIdIndexMap duration = %lld us\n", DurationUs(TimeNow() - start));

    TimePoint start1 = TimeNow();
    EVALUATOR_CHK_RET(matrix.InitMatrixByList(nodeList));
    EVALUATOR_INFO("InitMatrixByList duration = %lld us\n", DurationUs(TimeNow() - start1));
    EVALUATOR_CHK_RET(SetAllEdges(topo, matrix));

    matrixes.push_back(std::move(matrix));
    return HCCL_SUCCESS;
}

void TopoSplit::GetNodeIdIndexMap(std::vector<u32> &nodeList, std::unordered_map<u32, u32> &outMap)
{
    for (u32 i = 0; i < nodeList.size(); i++) {
        outMap[nodeList[i]] = i;
    }
}

void TopoSplit::GetNodeList(HcclTopology* topo, std::vector<u32> &nodeList)
{
    nodeList.reserve(topo->nodeNum);
    HcclNode *nodeListPtr = topo->nodeList;
    while (nodeListPtr != nullptr) {
        nodeList.push_back(nodeListPtr->nodeId);
        nodeListPtr = nodeListPtr->next;
    }
}

HcclResult TopoSplit::CheckNodeList(std::vector<u32> &nodeList)
{
    for (u32 i = 0; i < nodeList.size(); i++) {
        if (nodeList[i] != i) {
            EVALUATOR_ERROR("node id[%u] if diff with rank id[%u]", nodeList[i], i);
            return HCCL_E_PARA;
        }
    }
    return HCCL_SUCCESS;
}

HcclResult TopoSplit::SetAllEdges(HcclTopology* topo, AdjacencyMatrix<> &matrix)
{
    TimePoint start = TimeNow();
    HcclNode *nodeListPtr = topo->nodeList;

    while (nodeListPtr != nullptr) {
        HcclConnection *connectListPtr = nodeListPtr->connectionList;
        while (connectListPtr != nullptr) {
            HcclPort *portListPtr = connectListPtr->port;
            AdjaMatrixEdge edge;
            if (portListPtr != nullptr) {
                edge.ports = portListPtr;
            }
            EVALUATOR_CHK_RET(matrix.AddEdgeByIndex(nodeListPtr->nodeId, connectListPtr->peerNodeId, edge));
            connectListPtr = connectListPtr->next;
        }
        nodeListPtr = nodeListPtr->next;
    }
    EVALUATOR_INFO("SetAllEdges duration = %lld us\n", DurationUs(TimeNow() - start));
    return HCCL_SUCCESS;
}
} // namespace HcclEvaluator